package iface.aplicativo.integracao.dao;

import iface.aplicativo.negocio.entidade.Lancamento;
import iface.aplicativo.negocio.enumerador.TipoLancamentoEnum;
import iface.aplicativo.to.SituacaoContasTO;
import iface.aplicativo.util.DataUtilitario;
import iface.arquitetura.integracao.HibernateDAOAbstrato;

import java.util.Collection;
import java.util.Date;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;

@Repository
public class LancamentoDAO extends HibernateDAOAbstrato<Lancamento> {

	@SuppressWarnings("unchecked")
	public List<Lancamento> consultarLancamentosVencidasPorData(
			final Date dataConta, TipoLancamentoEnum tipoLancamento) {
		Criteria criteria = novoCriteria();

		if (dataConta != null) {
			Date atual = new Date();
			int mesConta = DataUtilitario.getMes(dataConta);
			int mesAtual = DataUtilitario.getMes(atual);

			if (mesConta < mesAtual) {
				criteria.add(Restrictions.lt("dtVencimento",
						DataUtilitario.calcularUltimoDiaMes(dataConta)));
			} else {
				criteria.add(Restrictions.lt("dtVencimento", dataConta));
			}
			criteria.add(Restrictions.isNull("dtBaixa"));
			criteria.add(Restrictions.eq("tipo", tipoLancamento));
		}

		return criteria.list();
	}

	@SuppressWarnings("unchecked")
	public List<Lancamento> consultarLancamentosAVencerPorData(
			final Date dataConta, TipoLancamentoEnum tipoLancamento) {
		Criteria criteria = novoCriteria();

		if (dataConta != null) {
			criteria.add(Restrictions.between("dtVencimento", dataConta,
					DataUtilitario.calcularUltimoDiaMes(dataConta)));
			criteria.add(Restrictions.isNull("dtBaixa"));
			criteria.add(Restrictions.eq("tipo", tipoLancamento));
		}

		return criteria.list();
	}

	@SuppressWarnings("unchecked")
	public List<Lancamento> consultarLancamentosPagosPorData(
			final Date dataConta, TipoLancamentoEnum tipoLancamento) {
		Criteria criteria = novoCriteria();

		if (dataConta != null) {
			criteria.add(Restrictions.between("dtVencimento",
					DataUtilitario.calcularPrimeiroDiaMes(dataConta),
					DataUtilitario.calcularUltimoDiaMes(dataConta)));
			criteria.add(Restrictions.isNotNull("dtBaixa"));
			criteria.add(Restrictions.eq("tipo", tipoLancamento));
		}

		return criteria.list();
	}

	@SuppressWarnings("unchecked")
	public List<Lancamento> consultarLancamentosPorFiltro(
			Date dataVencimentoInicial, Date dataVencimentoFinal,
			SituacaoContasTO situacaoContasTO) {
		Criteria criteria = novoCriteria();

		if (dataVencimentoInicial != null && dataVencimentoFinal != null) {
			criteria.add(Restrictions.between("dtVencimento",
					dataVencimentoInicial, dataVencimentoFinal));
		} else if (dataVencimentoInicial != null) {
			criteria.add(Restrictions.ge("dtVencimento", dataVencimentoInicial));
		} else if (dataVencimentoFinal != null) {
			criteria.add(Restrictions.le("dtVencimento", dataVencimentoFinal));
		}

		Date hoje = new Date();
		Disjunction disjunction = Restrictions.disjunction();

		if (situacaoContasTO != null) {
			if (situacaoContasTO.isAtrasados()) {
				Criterion cri = Restrictions.and(
						Restrictions.isNull("dtBaixa"),
						Restrictions.le("dtVencimento", hoje));
				disjunction.add(cri);
			}
			if (situacaoContasTO.isPagar()) {
				Criterion cri = Restrictions.and(
						Restrictions.isNull("dtBaixa"),
						Restrictions.eq("tipo", TipoLancamentoEnum.P));
				disjunction.add(cri);
			}
			if (situacaoContasTO.isPagos()) {
				Criterion cri = Restrictions.and(
						Restrictions.isNotNull("dtBaixa"),
						Restrictions.eq("tipo", TipoLancamentoEnum.P));
				disjunction.add(cri);
			}
			if (situacaoContasTO.isReceber()) {
				Criterion cri = Restrictions.and(
						Restrictions.isNull("dtBaixa"),
						Restrictions.eq("tipo", TipoLancamentoEnum.R));
				disjunction.add(cri);
			}
			if (situacaoContasTO.isRecebidos()) {
				Criterion cri = Restrictions.and(
						Restrictions.isNotNull("dtBaixa"),
						Restrictions.eq("tipo", TipoLancamentoEnum.R));
				disjunction.add(cri);
			}
		}
		criteria.add(disjunction);

		criteria.addOrder(Order.desc("dtVencimento"));

		return criteria.list();
	}

	public Collection<Lancamento> consultarLancamentosPorVendaVeiculoId(
			final Long idVendaVeiculo) {
		Criteria criteria = novoCriteria();
		criteria.createAlias("vendaVeiculo", "vendaVeiculo");

		if (idVendaVeiculo != null) {
			criteria.add(Restrictions.eq("vendaVeiculo.idVendaVeiculo",
					idVendaVeiculo));
		}

		return consultar(criteria);
	}

}
